package subumbo.game.renderer
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	
	import subumbo.game.physics.VerletPoint;

	public class Renderer extends EventDispatcher
	{
		private var _renderChain:Array;
		private var _references:Dictionary;
		private var _pointCanvas:DisplayObjectContainer; 
		private var _stickCanvas:DisplayObjectContainer;
		private var _renderCallback:Function; 
		
		public function Renderer(canvas:DisplayObjectContainer)
		{
			super(null);
			init(canvas);
		}
		
		private function init(canvas:DisplayObjectContainer):void
		{
			_stickCanvas = new Sprite();
			_pointCanvas = new Sprite();
			canvas.addChild(_stickCanvas);
			canvas.addChild(_pointCanvas);
			_renderChain = [];
			_references = new Dictionary();
		}
		
		public function start():void
		{
			_stickCanvas.addEventListener(Event.ENTER_FRAME, render);
		}
		
		public function stop():void
		{
			_stickCanvas.removeEventListener(Event.ENTER_FRAME, render);			
		}
		
		public function reset():void
		{
			stop();
			_renderChain = [];
			_references = new Dictionary();
			
			var i:int = _pointCanvas.numChildren;
			while( --i > -1) _pointCanvas.removeChildAt(0);
			i = _stickCanvas.numChildren;
			while( --i > -1) _stickCanvas.removeChildAt(0);
		}
		
		private function render(e:Event):void
		{
			var i:int = _renderChain.length
			var renderObject:RenderObject;
			while( --i > -1 )
			{
				RenderObject(_renderChain[i]).render();
			}
			if(_renderCallback!=null) _renderCallback.call(this);
		}
		
		public function addObject(obj:DisplayObject, renderable:Renderable, id:String=""):String
		{
			if(_references[id]) throw new Error("Renderer: Id is already in use.");
			var index:uint;
			var renderObject:RenderObject = new RenderObject(obj, renderable);
			index = _renderChain.push(renderObject);
			
			if(id == "") id = "gameObject_" + index;
			else id += "_" + index;	
			_references[id] = index;
			
			if(renderable is VerletPoint)
			{			
				_pointCanvas.addChild(obj);
			}
			else
			{
				_stickCanvas.addChild(obj);	
			}
			return id;
		}
		
		public function removeObject(id:String):Boolean
		{
			if(id == "" || id == null) return false;
			var index:int = _references[id]; 
			if(_pointCanvas.contains(_renderChain[index])) 	_pointCanvas.removeChildAt(index);
			else											_stickCanvas.removeChildAt(index);
			_renderChain.splice(index, 1);
			return true;
		}
	
		
		public function set renderCallback(val:Function):void
		{
			_renderCallback = val;
		}
	}
}